<?php if (!defined('BASEPATH'))exit('No direct script access allowed');

include_once 'ExceptionDAO.php';
include_once 'util/MapError.php';
include_once 'TOCategoria.php';

/**
 * DAO para operações de banco para categoria
 * 
 * @author Douglas Rafael
 */
class DAOCategoria extends CI_Model {
    
    /**
     * Lista todas as categorias cadastradas
     * 
     * @param int    $init          Posição inicial do cursor
     * @param int    $quant         Total de registros
     * @param string $orderby       Nome da coluna a ser ordenada
     * @param string $direction     Direção: ASC ou DESC
     * @return array TOCategoria    Array de objetos
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function select_all_categories($init, $quant, $orderby = NULL, $direction = NULL, $limit = TRUE) {
        try {
            $orderby != NULL && $direction != NULL ? $this->db->order_by($orderby, $direction) : $this->db->order_by('id', 'ASC');
            $result = $limit ? $this->db->get('categoria', $quant, $init) : $this->db->get('categoria');

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar as categorias.');
            } else {
                $categorias = array();
                foreach ($result->result() as $value) {
                    $categoria = new TOcategoria();
                    $categoria->id = $value->id;
                    $categoria->nome = $value->nome;
                    $categoria->descricao = $value->descricao;
                    $categoria->status = $value->status;
                    array_push($categorias, $categoria);
                }
                return $categorias;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

    /**
     * Retorna o Total geral categorias cadastrados.
     * 
     * @return int Total de resgistros
     */
    public function amount_all_categories() {
        return $this->db->count_all_results('categoria');
    }
    
    /**
     * Seleciona uma categoria de acordo com seu id
     * 
     * @param TOCategoria $categoria
     * @return boolean|TOCategoria
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_category(TOCategoria $categoria) {
        try {
            $this->db->where("id", $categoria->id);
            $result = $this->db->get('categoria');

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar selecionar categoria.');
            } else {
                $value = $result->row();
                
                $categoria = new TOcategoria();
                $categoria->id = $value->id;
                $categoria->nome = $value->nome;
                $categoria->descricao = $value->descricao;
                $categoria->status = $value->status;
                
                return $categoria;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    /**
     * Lista todas as categorias cadastradas de um item.
     * 
     * @param int $codigo_item
     * @return array TOCategoria
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function get_categories_item($codigo_item) {
        try {
            $this->db->select('categoria.id, categoria.nome, categoria.descricao, categoria.status');
            $this->db->join('categoria', 'categoria.id = categoria_has_item.categoria_id');
            $this->db->join('item', 'item.codigo = categoria_has_item.item_codigo');
            $this->db->where('item.codigo', $codigo_item);
            $result = $this->db->get('categoria_has_item');

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar listar categorias do item.');
            } else {
                $categorias = array();
                foreach ($result->result() as $value) {
                    $categoria = new TOcategoria();
                    $categoria->id = $value->id;
                    $categoria->nome = $value->nome;
                    $categoria->descricao = $value->descricao;
                    $categoria->status = $value->status;
                    
                    array_push($categorias, $categoria);
                }
                return $categorias;
            }
        } catch (ExceptionDAO $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Insere no banco de dados a categoria
     * 
     * @param TOcategoria $categoria
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_category(TOcategoria $categoria) {
        try {
            $result = $this->db->insert('categoria', $categoria);

            if (!$result) {
                throw new Exception();
            }
        } catch (Exception $erro) {
            //Traduz o tipo de erro de acordo com $num
            $erro = new MapError();
            throw new ExceptionDAO($erro->getError($this->db->_error_number(), $this->db->_error_message(), $categoria->nome));
        }
    }
    
    
    /**
     * Insere as categorias do item
     * 
     * @param  TOItem $item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function insert_category_item(TOItem $item) {
        try {
            $categorias = array();
            foreach ($item->categorias as $value){
                $data['categoria_id'] = $value->id;
                $data['item_codigo']  = $item->codigo;
                array_push($categorias, $data);
            }
            $result = $this->db->insert_batch('categoria_has_item', $categorias);
            
            $this->db->trans_complete();

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar inserir categorias do item.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Atualiza as categorias do item
     * - 1° As categorias desse livro já cadastradas são apagadas, e depois inseridas as novas
     * 
     * @param  TOItem $item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function update_category_item(TOItem $item) {
        try {
            $this->delete_category_item($item->codigo);
            $categorias = array();
            foreach ($item->categorias as $value) {
                $data['categoria_id'] = $value->id;
                $data['item_codigo'] = $item->codigo;
                array_push($categorias, $data);
            }
            $result = $this->db->insert_batch('categoria_has_item', $categorias);
            
            $this->db->trans_complete();

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar atualizar categorias do item.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    
    /**
     * Remove as categorias do item
     * 
     * @param  $codigo_item
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function delete_category_item($codigo_item) {
        try {
            $this->db->where('item_codigo', $codigo_item);
            $result = $this->db->delete('categoria_has_item');

            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar remover categorias do item.');
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

    /**
     * Atualiza dados da categoria
     * 
     * @param TOCategoria $categoria
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function update_category(TOCategoria $categoria) {
        try {
            $this->db->where('id', $categoria->id);
            $result = $this->db->update('categoria', $categoria);

            if (!$result) {
                //Traduz o tipo de erro de acordo com $num
                $erro = new MapError();
                throw new Exception($erro->getError($this->db->_error_number(), $this->db->_error_message(), $categoria->nome));
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }

    /**
     * Exclui categoria de acordo com o id
     * 
     * @param TOCategoria $categoria    Obejto categoria contendo dados para deletar
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function delete_category(TOCategoria $categoria) {
        try {
            $this->db->where_in('id', $categoria->id);
            $result = $this->db->delete('categoria');

            if (!$result) {
                //Traduz o tipo de erro de acordo com $num
                $erro = new MapError();
                throw new Exception($erro->getError($this->db->_error_number(), $this->db->_error_message(), $categoria->nome));
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
    /**
     * Efetua busca por categoria
     * 
     * @param type $init
     * @param type $quant
     * @param type $term
     * @param type $orderby
     * @param type $direction
     * @return array
     * @throws ExceptionDAO
     * @throws Exception
     */
    public function search_category($init, $quant, $term = NULL, $orderby = NULL, $direction = NULL) {
        try {
            $this->db->like('id', $term);
            $this->db->or_like('nome', $term);
            $orderby != NULL && $direction != NULL ? $this->db->order_by($orderby, $direction) : $this->db->order_by('id', 'ASC');
            $result = $this->db->get('categoria', $quant, $init);

            //Caso ocorra erro no select
            if (!$result) {
                throw new Exception('Ocorreu um erro de banco de dados ao tentar buscar categoria.');
            } else {
                $categorias = array();
                foreach ($result->result() as $value) {
                    $categoria = new TOcategoria();
                    $categoria->id = $value->id;
                    $categoria->nome = htmlentities($value->nome, ENT_QUOTES);
                    $categoria->descricao = htmlentities($value->descricao, ENT_QUOTES);
                    $categoria->status = $value->status;
                    array_push($categorias, $categoria);
                }
                return $categorias;
            }
        } catch (Exception $e) {
            throw new ExceptionDAO($e->getMessage());
        }
    }
    
     /**
     * Retorna a quantidade de registros da busca
     * 
     * @param string $term
     * @return int
     */
    public function amount_search_category($term) {
        $this->db->like('id', $term);
        $this->db->or_like('nome', $term);

        return $this->db->count_all_results('categoria');
    }

    
    /**
     * Retorna sugestões de categorias de acordo com o term digitado
     * Útil para utilizar no autocomplete
     * 
     * @param TOCategoria $categoria
     * @return type
     */
    public function suggestion_category(TOCategoria $categoria) {
        $this->db->like('nome', $categoria->nome);
        $result = $this->db->get('categoria');

        $categorias = array();
        if ($result) {
            foreach ($result->result() as $value) {
                $data['label'] = $value->nome;
                $data['id'] = $value->id;
                array_push($categorias, $data);
            }
            return $categorias;
        }
    }
}